/*******************************************************************
 *
 * Copyright (C), 2021-2022, Letstrong, All rights reserved.
 *
 * Author      : 
 * Create Time : 2020-12-15
 * Version     : v0.1
 * Description : 
 *******************************************************************/
 
/*----------------------------Head file----------------------------*/
#include "rwip_config.h"

#if (BLE_OTA_SERVER)
#include "wdt.h"
#include "ota_flash.h"
#include "ota_crc16.h"
#include "ota_protocol.h"
#include "hal_flash.h"

#define OTA_SF_LOG_ENABLE      1

#if OTA_SF_LOG_ENABLE
#include "log.h"
#define OTA_SF_LOG             LOG_DEBUG
#else
#define OTA_SF_LOG(...)
#endif

/*----------------------------macro file---------------------------*/
#define ota_flash_erase		hal_flash_erase_sector
#define ota_flash_write		hal_flash_write
#define ota_flash_read		hal_flash_read

/*----------------------------type define--------------------------*/
typedef struct {
	// Secure OAD uses the Signature for image validation instead of calculating a CRC, but the use
	// of CRC==CRC-Shadow for quick boot-up determination of a validated image is still used.
	uint32_t crc;       // CRC must not be 0x0000 or 0xFFFF.
	// User-defined Image Version Number - default logic uses simple a '!=' comparison to start an OAD.
	uint16_t ver;
	uint16_t len;        // Image length in 4-byte blocks (i.e. HAL_FLASH_WORD_SIZE blocks).
	uint32_t uid;     // User-defined Image Identification bytes.
	uint8_t crc_status;     // cur image crc status
	uint8_t sec_status;     // cur image sec status
	uint16_t rom_ver;     // Reserved space for future use.
} BankBootInfoHeader_t;

OtaFlashCtl_t otaFlashCtl;

/*----------------------------var define---------------------------*/							

/*-------------------------func declaration------------------------*/

/*-----------------------------------------------------------------*/

bool otaFlash_CheckHeader(uint8_t *buf, uint32_t len)
{
	if(len < sizeof(BankBootInfoHeader_t))
		return false;
	
	uint32_t uid = 0;
	memcpy((uint8_t*)&uid, &buf[8], sizeof(uid));
	OTA_SF_LOG("ImgHdr.uid = %x \r\n", uid);
	
	if(uid != OTA_APP_PART_UID) {
		ota_flash_erase(APP_TEMP_BIN_START_ADDR);	//Erase head to make ota file unvalid.
		return false;
	}
	
	return true;
}

void otaFlash_WriteData(uint8_t *buf, uint32_t len)
{
	uint32_t offset;
	uint32_t wrLen;
	uint8_t *ptr;

	ptr = buf;
	offset = APP_TEMP_BIN_START_ADDR + otaFlashCtl.writeSize;
	
	if(offset > APP_TEMP_BIN_END_ADDR) {
		LOG_ERROR("ota write out of size\n");
		return;
	}
	
	if(((offset+len-1)&0xFFFFFF00) != (offset&0xFFFFFF00)) {
		wrLen = 0x100 - (offset&0xFF);
		if((offset % HAL_FLASH_SECTOR_SIZE) == 0) {
			ota_flash_erase(offset);
		}
		ota_flash_write(offset, ptr, wrLen);
		offset += wrLen;
		ptr += wrLen;
		wrLen = len-wrLen;
	}
	else {
		wrLen = len;
	}
	if((offset % HAL_FLASH_SECTOR_SIZE) == 0) {
		ota_flash_erase(offset);
	}
	ota_flash_write(offset, ptr, wrLen);
	otaFlashCtl.writeSize += len;
}


bool otaFlash_CalculateCRC16(uint16_t imageCRC16, uint32_t imageSize)
{
	uint32_t i, len;
	uint16_t crc = 0xffff;

	for(i=0; i< imageSize; i+=sizeof(otaFlashCtl.flashBuf)) {
		len = imageSize - i;
		if(len > sizeof(otaFlashCtl.flashBuf)) {
			len = sizeof(otaFlashCtl.flashBuf);
		}
		ota_flash_read(APP_TEMP_BIN_START_ADDR + i, otaFlashCtl.flashBuf, len);
		crc = ota_crc16_calc(otaFlashCtl.flashBuf, len, crc);
	}
	
	OTA_SF_LOG("CheckCRC=%x, DownCRC=%x\r\n", crc, imageCRC16);
	if(crc != imageCRC16) {
		return false;
	}
	return true;
}


#endif	//#if (BLE_OTA_SERVER)
